package com.test;

import lombok.Data;

import java.util.*;
import java.util.concurrent.*;

/**
 * @author Sanmier
 * @version 1.0
 * @date 2024/4/26
 */
public class LocalCacheAndConcurrent {
    private static final ConcurrentHashMap<Integer, LocalCache> localCacheMap = new ConcurrentHashMap<>(100);

    @Data
    public class ShopInfo{
        //商户Id
        private Integer id;
        //商户名称
        private String name;
        //商户地址
        private String address;
    }

    public class ShopService{
        public Map<Integer, String> getShopName(List<Integer> shopIds){
            return Collections.emptyMap();
        }
        public Map<Integer, String> getShopAddress(List<Integer> shopIds){
            return Collections.emptyMap();
        }
    }

    public class AService{
        private ShopService shopService = new ShopService();

        public Map<Integer, ShopInfo> getShopInfo(List<Integer> shopIds) throws ExecutionException, InterruptedException {
            Map<Integer, ShopInfo> resultMap = new ConcurrentHashMap<>();
            Map<Integer, ShopInfo> resultByServiceMap = new ConcurrentHashMap<>();
            List<Integer> arrayList = new ArrayList<>();
            //拆寻本地缓存
            for (Integer shopId : shopIds) {
                if (localCacheMap.containsKey(shopId)){
                    resultMap.put(shopId, localCacheMap.get(shopId).getShopInfo());
                }else {
                    arrayList.add(shopId);
                }
            }
            //每批次最多处理数量不大于十
            int batchSize = 10;
            //计算分批数
            int batches = (int)Math.ceil((double) arrayList.size() / batchSize);
            List<CompletableFuture<Void>> futures = new ArrayList<>();
            //建线程池
            ThreadPoolExecutor ex = new ThreadPoolExecutor(batches, batches, 0L, TimeUnit.SECONDS, new SynchronousQueue<>());
            for (int i = 0; i < batches; i++) {
                //计算该批次商户的id范围
                int start = i * batchSize;
                int end = Math.min(start + batchSize, arrayList.size());
                List<Integer> batchIds = arrayList.subList(start, end);

                CompletableFuture<Map<Integer, ShopInfo>> resultFuture = CompletableFuture.supplyAsync(() -> {
                    Map<Integer, String> shopNameMap = shopService.getShopName(batchIds);
                    return shopNameMap;
                }, ex).thenCombineAsync(CompletableFuture.supplyAsync(() -> {
                    Map<Integer, String> shopAddressMap = shopService.getShopAddress(batchIds);
                    return shopAddressMap;
                }, ex), (shopNameMap, shopAddressMap) -> {
                    for (Integer shopId : shopNameMap.keySet()) {
                        String shopAddressById = shopAddressMap.get(shopId);
                        ShopInfo shopInfo = new ShopInfo();
                        LocalCache lc = new LocalCache();
                        shopInfo.setId(shopId);
                        shopInfo.setName(shopNameMap.get(shopId));
                        shopInfo.setAddress(shopAddressById);
                        lc.setKey(shopId);
                        lc.setShopInfo(shopInfo);
                        //放入缓存
                        localCacheMap.put(shopId, lc);
                        resultByServiceMap.put(shopId, shopInfo);
                    }
                    return resultByServiceMap;
                }, ex);
                resultMap.putAll(resultFuture.get());
            }
            ex.shutdown();
            //localCacheMap.clear();
            return resultMap;
        }
    }

    public void putLocalCache(Integer key, ShopInfo shopInfo){
        LocalCache localCache = new LocalCache();
        if (!localCacheMap.containsKey(key)){
            localCache.setKey(key);
        }else {
            localCache = localCacheMap.get(key);
        }
        localCache.setShopInfo(shopInfo);
        localCacheMap.put(key,localCache);
    }

    public LocalCache getLocalCache(Integer key){
        if (!localCacheMap.containsKey(key)){
            return null;
        }
        return localCacheMap.get(key);
    }

    @Data
    class LocalCache{
        private Integer key;
        private ShopInfo shopInfo;
    }
}

    //@Test
    //public void test1() throws ExecutionException, InterruptedException {
    //    List<Integer> list = new ArrayList<>();
    //    for (int i = 1; i <= 100; i++) {
    //        list.add(i);
    //    }
    //    System.out.println(list);
    //    Map<Integer, ShopInfo> shopInfo = new AService().getShopInfo(list);
    //    System.out.println(shopInfo);
    //}

//public class ShopService{
//    public Map<Integer, String> getShopName(List<Integer> shopIds){
//        Map<Integer, String> map = new HashMap<>();
//        for (Integer shopId : shopIds) {
//            map.put(shopId, "testName");
//        }
//        return map;
//    }
//    public Map<Integer, String> getShopAddress(List<Integer> shopIds){
//        Map<Integer, String> map = new HashMap<>();
//        for (Integer shopId : shopIds) {
//            map.put(shopId, "testAddress");
//        }
//        return map;
//    }
//}
